

#include <wcs.h>
#include <pgwcsl.h>

#define CACHE_SIZE 256



#include "coord_conv.h"



//typedef int (*coord_conv_func)(double , double , double *, double *, void *);

typedef struct _conv_function_struct {
  coord_conv_func cf1;
  void * cf1_data;
  coord_conv_func cf2;
  void * cf2_data;
} conv_function_struct;

#define CONV_FUNCTION_STRUCT_CLEN (sizeof(conv_function_struct)/sizeof(char))
#define CONV_FUNCTION_STRUCT_P_CLEN (sizeof(conv_function_struct *)/sizeof(char))

#define wcs_bb_ F77_FUNC(wcs_bb, WCS_BB)

void wcs_bb_(opcode, nlc, nli, nld, nlcprm, nliprm, nldprm, world, pixel, contrl,
            contxt, ierr)

const int *opcode, *nlc, *nli, *nld;
const char *nlcprm;
int *nliprm;
double *nldprm;
double *world;
double *pixel;
int *contrl;
double contxt[20];
int *ierr;

{
   double world2[2];
   int nlc2 = 1;

   conv_function_struct *cf = (conv_function_struct *)nlcprm;

   if (*opcode > 0) {// world coordinate given

     cf->cf2(world[0], world[1], world2, world2+1, cf->cf2_data);

     pgwcsl_(opcode, &nlc2, nli, nld, nlcprm, nliprm, nldprm, 
	     world2, pixel, contrl, contxt, ierr);
     
   } else if (*opcode < 0) { // pixel coordinate given

     pgwcsl_(opcode, &nlc2, nli, nld, nlcprm, nliprm, nldprm, 
	     world2, pixel, contrl, contxt, ierr);

     cf->cf1(world2[0], world2[1], world, world+1, cf->cf1_data);

   } else  {
     pgwcsl_(opcode, &nlc2, nli, nld, nlcprm, nliprm, nldprm, 
	     world, pixel, contrl, contxt, ierr);
   }

   return;
}



int wcsgrid_bb(struct wcsprm *wcs, float x1, float y1, float x2, float y2, 
	       char *coord_format, int labctl,
	       int labden,
	       int axis_num, // axis number to draw grid
	       int ng, double *grid,
	       conv_function_struct *cfs)
{
  float blc[2];
  float trc[2]; 
  char idents[3][80];
  int ci[7]; // colors for plots, trash values as it will be ignored
  int gcode[] = {0, 0}; 
  //char nlcprm[1]; // junk value. doc says nlcprm > 1, but not sure.
  char nlcprm[CONV_FUNCTION_STRUCT_P_CLEN]; // junk value. doc says nlcprm > 1, but not sure.
  double nldprm[1];
  int ng1=0, ng2=0;
  double *grid1, *grid2;
  double grid_default[] = {0.};

  int ic = -1;
  double cache[CACHE_SIZE+1][4];
  int status;


  /*char nlcprm[1];
  int  hdunum = 1, hdutype, i, naxes, nkeyrec,
  nreject, nwcs, status;*/

  //(conv_function_struct *) nlcprm = cfs;

  blc[0] = x1;
  blc[1] = y1;

  trc[0] = x2;
  trc[1] = y2;

  idents[0][0] = '\0';
  idents[1][0] = '\0';
  idents[2][0] = '\0';

  if (axis_num == 1) {
    gcode[0] = 2;
    ng1=ng;
    grid1=grid;
    grid2=grid_default;
  } else if (axis_num == 2) {
    gcode[1] = 2;
    ng2=ng;
    grid1=grid_default;
    grid2=grid;
  } else {
    return 1;
  }

  status = wcsset(wcs);

  if (cfs) {
    cpgsbox(blc, trc, idents, coord_format, 
	    labctl, labden, ci, // labeling related
	    gcode, // 1: grid, 2: tick, 0: nothing
	    0.0, // tick length.
	    ng1, grid1, ng2, grid2, 0, // grid related.
	    wcs_bb_, 
	    CONV_FUNCTION_STRUCT_P_CLEN, WCSLEN, 1, 
	    (char *) cfs, (int *)(wcs), nldprm, // wcs related.
	    CACHE_SIZE, &ic, cache, // cache related.
	    &status);
  } else {
    cpgsbox(blc, trc, idents, coord_format, 
	    labctl, labden, ci, // labeling related
	    gcode, // 1: grid, 2: tick, 0: nothing
	    0.0, // tick length.
	    ng1, grid1, ng2, grid2, 0, // grid related.
	    pgwcsl_, 
	    1, WCSLEN, 1, 
	    nlcprm, (int *)(wcs), nldprm, // wcs related.
	    CACHE_SIZE, &ic, cache, // cache related.
	    &status);
  }

  return status;
}


int wcsgrid_jj(struct wcsprm *wcs, float x1, float y1, float x2, float y2, 
	       char *coord_format, int labctl,
	       int labden,
	       int axis_num, // axis number to draw grid
	       int ng, double *grid)
{

  return wcsgrid_bb(wcs,  x1,  y1,  x2,  y2, 
		    coord_format, labctl,
		    labden,
		    axis_num, // axis number to draw grid
		    ng, grid,
		    NULL);
}
